22 - 3.1 Ausführung von Programmen: Übersetzen, Binden [ID:16466]
50 von 112 angezeigt

Im letzten Kapitel haben wir uns damit beschäftigt, wie man C-Programme schreibt,

wie die Programmiersprache aufgebaut ist. Und in Kapitel 3 jetzt möchte ich relativ

kurz darauf eingehen, wie man jetzt von so einem C-Programm, das man mit einem Editor

erstellt hat und in einer Datei abgelegt hat, wie man von diesem C-Programm zu einer Programmausführung,

das nennt man dann ein Prozess, kommt. Im ersten Abschnitt dieses Kapitels möchte ich zusammenfassen,

wie man von einem C-Programm zum ausführbaren Programm, dem sogenannten Executable, kommt.

Also mit den Schritten, die wir zum Teil ja schon kennengelernt haben. Zunächst der C-Präprozessor,

der eine Vorverarbeitung macht, dann der eigentliche Compiler. Der Assemblierschritt

ist heutzutage eigentlich ein inherenter Bestandteil des Compilerschrittes. Man kann

aber diese Assemblerstufe auch noch separat ansteuern und sich auch den Assemblercode vom

Compiler ausgeben lassen und ihn dann weiter übersetzen. Und dann schließlich das Binden

mit anderen Modulen oder das Binden mit Modulen aus Bibliotheken. Und beim Binden unterscheiden wir

auch nochmal das Statische und das Dynamische Binden. Und auch darauf möchte ich im Detail etwas eingehen.

Im zweiten Abschnitt dieses Kapitels werde ich dann die Begriffe Programme und Prozesse kurz

vorstellen und die Speicherorganisation eines Programms im Gegensatz zur Speicherorganisation

eines Prozesses darstellen und kurz einen Überblick darüber geben, was eben passiert,

wenn man ein Programm lädt. Und zwar ein statisch gebundenes oder ein dynamisch gebundenes Programm.

Ja und schließlich im dritten Abschnitt werde ich einen kurzen Überblick über die Prozesszustände

geben, dann wie man einen Prozess erzeugt, wie man ein Programm ausführt und was es

ansonsten noch an Operationen auf Prozessen so gibt. Ja schauen wir uns also erstmal an,

wie man von so einem C-Quellcode zum ausführbaren Programm kommt. Der erste Schritt an dieser

Stelle ist der Präprozessor, den wir uns ja ganz knapp schon mal angeschaut hatten. Die Hauptaufgaben

vom Präprozessor sind das Entfernen von Kommentaren, denn die braucht man zwar für die Lesbarkeit des

Quellcodes, aber der Compiler braucht die gar nicht und das Auswerten von Präprozessoranweisungen.

Es werden also Include-Dateien eingefügt, es werden Makros expandiert und es wird makroabhängiger

Code entfernt für den Fall, dass er eben abhängig von den Makrodefinitionen nicht mit übersetzt

werden soll. Ein Beispiel für so einen makroabhängigen Codeabschnitt habe ich hier dargestellt. Sie

schreiben hin ifdef-debug und endif-debug und alle Zeilen, die zwischen diesem ifdef und endif

stehen, werden nur dann vom Präprozessor in der Quelldatei drin gelassen, wenn dieses makrodebug

definiert ist. Das können Sie natürlich machen, indem Sie einfach vorher define-debug hinschreiben.

Sie müssen ihm keinen Wert geben, es reicht, wenn Sie es einfach definieren. Wenn Sie das irgendwo

am Anfang der Datei hineinschreiben, dann werden alle Codezeilen, die eben zwischen diesem ifdef und

endif stehen, mitkompiliert und wenn Sie das oben rausnehmen, dieses define-debug, dann wird dieser

debug-output eben nicht mehr mitkompiliert. Sie können so ein makro auch beim Kompilieren auf

der Kommandozeile definieren mit "-d debug", und dann brauchen Sie an der Stelle gar nicht die

Quelldatei verändern, sonst können Sie das zum Beispiel auf der Ebene des Makefiles machen.

Das Zwischenergebnis von dem Präprozessorlauf kann man sich auch anschauen. Je nach Compiler gibt

es die Option "-p", da können Sie aus einer Datei.c ein Datei.i erzeugen, indem dann eben die Ausgabe

des Präprozessors nachgeschaut werden kann, oder Sie können mit "-cc-e", Datei.c, auf der

Standalausgabe des Compilers den Präprozessor-output ausgeben lassen und den dann irgendwo

abspeichern, indem Sie zum Beispiel die Ausgabe umlenken. Ja, und wenn der C-Präprozessor dann

sein Vorverarbeitungsergebnis irgendwo intern abgelegt hat, kommt als nächstes der eigentliche

Compiler und der, wenn man es jetzt in einzelnen Schritten betrachtet, übersetzt den C-Code erstmal

in Assembler. Wobei man sagen muss, moderne Compiler heutzutage haben diese Zwischenstufe

nicht mehr, sondern die erzeugen daraus unter Umständen irgendwelche Zwischencodes und aus denen

dann den eigentlichen ausführbaren Maschinencode. Aber konzeptionell kann man sich es also so

vorstellen und früher haben Compiler auch in mehreren Stufen so gearbeitet. Es wird

also erstmal Assembler daraus erzeugt und wie gesagt, also wenn der Assemblercode nicht

explizit angefordert wird, dann passiert ein direkter Übergang vom Kompilieren zum Assemblieren

zu Schritt 3. Das Zwischenergebnis dieses Compiler zu Assembler übersetzens kann man aber

Teil einer Videoserie :

Zugänglich über

Offener Zugang

Dauer

00:11:39 Min

Aufnahmedatum

2020-05-25

Hochgeladen am

2020-05-25 09:26:26

Sprache

de-DE

Tags

module programmstruktur Variablen Datentypen Preprozessor Gültigkeit
Einbetten
Wordpress FAU Plugin
iFrame
Teilen